﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ProjectEuler
{
    class Program
    {
        static void Main(string[] args)
        {
            //Problem1();
            //Problem2();
            //Problem6();
            //Problem5();
            Problem3();

            Console.ReadKey();
        }

        private static void Problem3()
        {
            long num = 600851475143;
            long divisor = 2;

            List<long> factors = new List<long>();
            
            while ((num - divisor) > 0)
            {
                var res = num % divisor;
                Console.WriteLine(res);
                if ((num % divisor) == 0)
                {
                    factors.Add(divisor);
                    num = (num / divisor);
                    divisor = 2;
                }
                else
                {
                    divisor++;
                }
            }

            Console.WriteLine("Composite = {0}", 600851475143);
            Console.WriteLine("Factors:");
            foreach (var factor in factors)
            {
                Console.WriteLine(factor);
            }
            Console.WriteLine("Largest prime factor = {0}", factors.Max());
        }

        private static void Problem5()
        {
            var sq = Enumerable.Range(2, 19);
            int number = 2520;
            bool search = true;

            while (search)
            {
                number += 2;
                foreach (var item in sq)
                {
                    if (Math.IEEERemainder(number, item) != 0)
                    {
                        search = true;
                        break;
                    }
                    search = false;
                }
            }

            Console.WriteLine("Number = {0}", number);
        }

        private static void Problem6()
        {
            var sq = Enumerable.Range(1, 100);

            var sumOfSqr = (from n in sq
                            select (n * n)).Sum();

            var sqrOfSum = Math.Pow(sq.Sum(), 2);

            Console.WriteLine("Diff = {0}", sqrOfSum - sumOfSqr);
        }

        private static void Problem2()
        {
            List<long> values = new List<long>();

            long prev = 0;
            long last = 0;
            while (last < 4000000)
            {
                if (values.Count == 0)
                {
                    last++;
                    values.Add(last);
                    prev = 0;
                }
                else if (values.Count == 1)
                {
                    last++;
                    values.Add(last);
                    prev = 1;
                }
                else
                {
                    long current = last + prev;
                    values.Add(current);
                    prev = last;
                    last = current;
                }
            }

            var sum = (from n in values
                       where (n % 2) == 0
                       select n).Sum();
            Console.WriteLine("Sum = {0}", sum);
        }

        private static void Problem1()
        {
            Console.WriteLine("Enter first number:");
            int first = int.Parse(Console.ReadLine());

            Console.WriteLine("Enter second number:");
            int second = int.Parse(Console.ReadLine());

            Console.WriteLine("Enter max:");
            int max = int.Parse(Console.ReadLine());

            var firstSq = Enumerable.Range(1, (max - 1) / first);
            var secondSq = Enumerable.Range(1, (max - 1) / second);

            var firstTotal = from n in firstSq
                             select (n * first);

            var secondTotal = from n in secondSq
                              select (n * second);

            var total = firstTotal.Concat(secondTotal).Distinct();

            Console.WriteLine("Grand Total = {0}", total.Sum());
        }
    }

    public static class Ext
    {
        public static int NextPrime(this int num)
        {
            return (int)InternalNextPrime(num);
        }

        public static long NextPrime(this long num) 
        {
            return InternalNextPrime(num);
        }

        public static bool IsPrime(this int num)
        {
            return InternalIsPrime(num);
        }

        public static bool IsPrime(this long num)
        {
            return InternalIsPrime(num);
        }

        private static long InternalNextPrime(long num)
        {
            if (num == 0 || num == 1)
            {
                return 2;
            }
            if (num == 2)
            {
                return 3;
            }
            if (num == 3)
            {
                return 5;
            }
            if (num == 4)
            {
                return 5;
            }
            if (num == 5)
            {
                return 7;
            }
            if (num == 6)
            {
                return 7;
            }
            if (num == 7)
            {
                return 11;
            }
            if (num == 8)
            {
                return 11;
            }
            if (num == 9)
            {
                return 11;
            }
            if (num == 10)
            {
                return 11;
            }

            bool found;
            do
            {
                found = true;
                num++;
                while ((num % 2) == 0)
                {
                    num++;
                }

                int sqr = (int)Math.Sqrt(num);
                var divisors = new List<int>();
                for (int i = 3; i < sqr; i++)
                {
                    if ((i % 2) != 0)
                    {
                        divisors.Add(i);
                    }
                }

                foreach (var div in divisors)
                {
                    if ((num % div) == 0)
                    {
                        found = false;
                        break;
                    }
                }
            }
            while (!found);


            return num;
        }

        private static bool InternalIsPrime(long num)
        {
            if (num == 0)
            {
                return false;
            }
            if (num == 1)
            {
                return true;
            }
            if (num == 2)
            {
                return true;
            }
            if ((num % 2) == 0)
            {
                return false;
            }
            if (num == 3)
            {
                return true;
            }
            if (num == 5)
            {
                return true;
            }
            if (num == 7)
            {
                return true;
            }
            
            return false;
        }
    }
}
